﻿/*--------------------------------------------------------------------------------
 * Adaptive Intelligence - Foundation Framework Class Library
 * Version 2.00
 * 
 * ZIP Data Descriptor Class
 * 		Represents and manages an optional data descriptor post-file-data record.
 *------------------------------------------------------------------------------*/

/*--------------------------------------------------------------------------------
 * System Imports
 *------------------------------------------------------------------------------*/
using System;
using System.IO;

namespace Adaptive.Foundation.IO.Zip
{
    /// <summary>
    /// Represents and manages an optional data descriptor post-file-data record.
    /// </summary>
    /// <remarks>
    /// This descriptor exists only if bit 3 of the general purpose bit flag is set.
    /// It is byte aligned and immediately follows the last byte of compressed data.
    /// This descriptor is used only when it was not possible to seek in the output .ZIP file.
    /// </remarks>
    public sealed class ZipDataDescriptor : ZipIoBase, IStorable 
    {

        /*--------------------------------------------------------------------------------
         * Private Member Declarations
         *------------------------------------------------------------------------------*/
        #region Private Member Declarations
        /// <summary>
        /// Data entry signature.
        /// </summary>
        private byte[] _signature = new Byte[] { 80, 75, 7, 8 };
        /// <summary>
        /// The cyclic-redundancy check value.
        /// </summary>
        private int _crc32;
        /// <summary>
        /// The size of the data when compressed.
        /// </summary>
        private int _compressedSize;
        /// <summary>
        /// The size of the data when un-compressed.
        /// </summary>
        private int _uncompressedSize;
        #endregion

        /*--------------------------------------------------------------------------------
         * Constructor / Dispose / Destructor Methods
         *------------------------------------------------------------------------------*/
        #region Constructor / Dispose / Destructor Methods
        /// <summary>
        /// Initializes a new instance of the <see cref="ZipDataDescriptor" /> class.
        /// </summary>
        /// <remarks>
        /// This is the default constructor.
        /// </remarks>
        public ZipDataDescriptor()
            : base()
        {
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="ZipDataDescriptor" /> class.
        /// </summary>
        /// <param name="crc32">The cyclic-redundancy check value.</param>
        /// <param name="compressedSize">The size of the data when compressed.</param>
        /// <param name="uncompressedSize">The size of the data when un-compressed.</param>
        public ZipDataDescriptor(int crc32, int compressedSize, int uncompressedSize)
            : base()
        {
            _crc32 = crc32;
            _compressedSize = compressedSize;
            _uncompressedSize = uncompressedSize;

        }
        #endregion

        /*--------------------------------------------------------------------------------
         * Public Properties
         *------------------------------------------------------------------------------*/
        #region Public Properties
        /// <summary>
        /// Gets or sets the cyclic-redundancy check value.
        /// </summary>
        /// <value>
        /// The CRC-32 value.
        /// </value>
        public int Crc32
        {
            get
            {
                return _crc32;
            }
            set
            {
                _crc32 = value;
            }
        }
        /// <summary>
        /// Gets or sets the size of the data when compressed.
        /// </summary>
        /// <value>
        /// The size of the data when compressed, in bytes.
        /// </value>
        public int CompressedSize
        {
            get
            {
                return _compressedSize;
            }
            set
            {
                _compressedSize = value;
            }
        }
        /// <summary>
        /// Gets or sets the size of the data when un-compressed.
        /// </summary>
        /// <value>
        /// The size of the data when uncompressed, in bytes.
        /// </value>
        public int UncompressedSize
        {
            get
            {
                return _uncompressedSize;
            }
            set
            {
                _uncompressedSize = value;
            }
        }

        #endregion

        /*--------------------------------------------------------------------------------
         * Public Methods / Functions
         *------------------------------------------------------------------------------*/
        #region Public Methods / Functions
        /// <summary>
        /// Loads the content for the instance from the specified stream.
        /// </summary>
        /// <param name="reader">An open <see cref="BinaryReader" /> used to read data from the
        /// underlying stream.</param>
        /// <returns>
        /// <b>true</b> if the load operation is successful; otherwise, <b>false</b>.
        /// </returns>
        public override bool Load(BinaryReader reader)
        {
            bool returnValue = false;

            try
            {
                _signature = reader.ReadBytes(4);
                _crc32 = reader.ReadInt32();
                _compressedSize = reader.ReadInt32();
                _uncompressedSize = reader.ReadInt32();
                returnValue = true;
            }
            catch (IOException ex)
            {
                OnReadException(new IoExceptionEventArgs(ex));
            }
            return returnValue;
        }
        /// <summary>
        /// Saves the content for the instance to the specified stream.
        /// </summary>
        /// <param name="writer">An open <see cref="BinaryWriter" /> used to write data to the
        /// underlying stream.</param>
        /// <returns>
        /// <b>true</b> if the save operation is successful; otherwise, <b>false</b>.
        /// </returns>
        public override bool Save(BinaryWriter writer)
        {
            bool returnValue = false;

            try
            {
                writer.Write(_signature);
                writer.Write(_crc32);
                writer.Write(_compressedSize);
                writer.Write(_uncompressedSize);
                returnValue = true;
            }
            catch (IOException ex)
            {
                OnWriteException(new IoExceptionEventArgs(ex));
            }
            return returnValue;
        }
        #endregion
    }
}